package com.sss.portalrimac.web.registro.validator;

import org.apache.commons.lang.CharUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.validation.Errors;

import com.sss.portalrimac.infraestructure.util.RegularExpressionUtil;
import com.sss.portalrimac.web.registro.viewmodel.Contacto;
import com.sss.portalrimac.web.registro.viewmodel.PersonaJuridica;
import com.sss.portalrimac.web.shared.constant.Constant;
import com.sss.portalrimac.web.shared.constant.MessageCodeConstant;

@Service("clienteJuridicoValidator")
public class ClienteJuridicoValidator extends AbstractRegistroValidator
{
	public static final String CAMPO_ACEPTA_TERMINOS = "aceptaTerminos";
	public static final String CAMPO_ANEXO_CONTACTO = "contacto.anexo";
	public static final String CAMPO_APEMAT_CONTACTO = "contacto.apellidoMaterno";
	public static final String CAMPO_APEPAT_CONTACTO = "contacto.apellidoPaterno";
	public static final String CAMPO_CARGO_CONTACTO = "contacto.cargo";
	public static final String CAMPO_EMAIL_CONTACTO = "contacto.email";
	public static final String CAMPO_NOMBRES_CONTACTO = "contacto.nombres";
	public static final String CAMPO_NRODOC_CONTACTO = "contacto.numeroDocumento";
	public static final String CAMPO_NUMERO_DOCUMENTO = "numeroDocumento";
	public static final String CAMPO_NUMERO_FACTURA = "numeroFactura";
	public static final String CAMPO_POLIZA = "poliza";
	public static final String CAMPO_PREGUNTA_SEGURIDAD = "preguntaSeguridad";
	public static final String CAMPO_RESPUESTA_SEGURIDAD = "respuestaSeguridad";
	public static final String CAMPO_TELEFONO_CONTACTO = "contacto.telefono";
	private static final int[] SECUENCIA_RUC = new int[] { 5, 4, 3, 2, 7, 6, 5, 4, 3, 2 };

	public boolean supports(Class<?> clazz)
	{
		return PersonaJuridica.class.isAssignableFrom(clazz);
	}

	public void validate(Object command, Errors errors)
	{
		PersonaJuridica persona = (PersonaJuridica) command;
		validarNumeroDocumento(persona.getNumeroDocumento(), errors);
		validarDatoValidacion(persona, errors);
		validarRequerido(errors, CAMPO_NOMBRES_CONTACTO);
		validarRequerido(errors, CAMPO_APEPAT_CONTACTO);
		validarRequerido(errors, CAMPO_APEMAT_CONTACTO);
		validarNumeroDocumentoContacto(persona.getContacto(), errors);
		validarCorreoElectronicoContacto(persona.getContacto().getEmail(), errors);
		validarRequerido(errors, CAMPO_CARGO_CONTACTO);
		validarTelefonosContacto(persona.getContacto().getTelefono(), persona.getContacto().getAnexo(), errors);
		validarPreguntaSeguridad(persona.getPreguntaSeguridad(), errors);
		validarRespuestaSeguridad(persona.getRespuestaSeguridad(), errors);
		validarTerminosYCondiciones(persona.getAceptaTerminos(), errors);
	}

	private boolean esRUCValido(String ruc)
	{
		if (StringUtils.isBlank(ruc) || ruc.length() != 11 || !StringUtils.isNumeric(ruc))
		{
			return false;
		}
		int dv = CharUtils.toIntValue(ruc.charAt(10));
		int sum = 0;
		for (int i = 0; i < 10; i++)
		{
			int d = CharUtils.toIntValue((ruc.charAt(i)));
			sum += (d * SECUENCIA_RUC[i]);
		}
		int dc = 11 - (sum % 11);
		switch (dc)
		{
			case 10:
				dc = 0;
				break;
			case 11:
				dc = 1;
				break;
			default:
				break;
		}
		return dv == dc;
	}

	private void validarDatoValidacion(PersonaJuridica persona, Errors errors)
	{
		if (Constant.TIPO_VALIDACION_FACTURA.equals(persona.getDatoValidacion()))
		{
			validarFactura(persona.getSerieFactura(), persona.getNumeroFactura(), errors);
		}
		else if (Constant.TIPO_VALIDACION_POLIZA.equals(persona.getDatoValidacion()))
		{
			validarPoliza(persona.getProducto(), persona.getPoliza(), errors);
		}
	}

	private void validarAnexoContacto(String anexoContacto, Errors errors)
	{
		if (!errors.hasFieldErrors(CAMPO_ANEXO_CONTACTO)
				&& !RegularExpressionUtil.validar(RegularExpressionUtil.EXREG_NUMEROS, anexoContacto))
		{
			rechazarValor(errors, CAMPO_ANEXO_CONTACTO, MessageCodeConstant.MSJ_ERROR_REGISTRO_FORMAT_ANX_CONTACTO);
		}
	}

	private void validarCorreoElectronicoContacto(String email, Errors errors)
	{
		validarRequerido(errors, CAMPO_EMAIL_CONTACTO);
		if (!errors.hasFieldErrors(CAMPO_EMAIL_CONTACTO)
				&& !RegularExpressionUtil.validar(RegularExpressionUtil.EXREG_EMAIL, email))
		{
			rechazarValor(errors, CAMPO_EMAIL_CONTACTO, MessageCodeConstant.MSJ_ERROR_REGISTRO_FORMAT_EMAIL, "");
		}
	}

	private void validarFactura(String serie, String numero, Errors errors)
	{
		if (StringUtils.isBlank(serie) || StringUtils.isBlank(numero))
		{
			rechazarValor(errors, CAMPO_NUMERO_FACTURA, MessageCodeConstant.MSJ_ERROR_REQUIRED1, "Campo");
		}
		else if (!StringUtils.isAlphanumeric(serie) || !StringUtils.isNumeric(numero))
		{
			rechazarValor(errors, CAMPO_NUMERO_FACTURA, MessageCodeConstant.MSJ_ERROR_REGISTRO_NRO_FACTURA_NO_VALIDO);
		}
		else if (serie.length() > 4)
		{
			rechazarValor(errors, CAMPO_NUMERO_FACTURA,
					MessageCodeConstant.MSJ_ERROR_REGISTRO_LONGITUD_SERIE_FACTURA_NO_VALIDA);
		}
		else if (numero.length() > 10)
		{
			rechazarValor(errors, CAMPO_NUMERO_FACTURA,
					MessageCodeConstant.MSJ_ERROR_REGISTRO_LONGITUD_NRO_FACTURA_NO_VALIDA);
		}
	}

	private void validarNumeroDocumento(String ruc, Errors errors)
	{
		validarRequerido(errors, CAMPO_NUMERO_DOCUMENTO);
		if (!errors.hasFieldErrors(CAMPO_NUMERO_DOCUMENTO) && !esRUCValido(ruc))
		{
			rechazarValor(errors, CAMPO_NUMERO_DOCUMENTO, MessageCodeConstant.MSJ_ERROR_REGISTRO_RUC_NO_VALIDO, "");
		}
	}

	private void validarNumeroDocumentoContacto(Contacto contacto, Errors errors)
	{
		validarRequerido(errors, CAMPO_NRODOC_CONTACTO);
		if (!errors.hasFieldErrors(CAMPO_NRODOC_CONTACTO))
		{
			if (Constant.TIPO_DOCUMENTO_DNI.equals(contacto.getTipoDocumento())
					&& !esDNIValido(contacto.getNumeroDocumento()))
			{
				rechazarValor(errors, CAMPO_NRODOC_CONTACTO, MessageCodeConstant.MSJ_ERROR_REGISTRO_FORMAT_DNI);
			}
		}
	}

	private void validarPoliza(String producto, String poliza, Errors errors)
	{
		if (StringUtils.isBlank(producto) || StringUtils.isBlank(poliza))
		{
			rechazarValor(errors, CAMPO_POLIZA, MessageCodeConstant.MSJ_ERROR_REQUIRED1, "Campo");
		}
		else if (!StringUtils.isNumeric(producto) || !StringUtils.isNumeric(poliza))
		{
			rechazarValor(errors, CAMPO_POLIZA, MessageCodeConstant.MSJ_ERROR_REGISTRO_NRO_POLIZA_NO_VALID0);
		}
		else if (producto.length() > 4)
		{
			rechazarValor(errors, CAMPO_POLIZA, MessageCodeConstant.MSJ_ERROR_REGISTRO_LONGITUD_CODPRODUCTO_NO_VALIDA);
		}
		else if (poliza.length() > 11)
		{
			rechazarValor(errors, CAMPO_POLIZA, MessageCodeConstant.MSJ_ERROR_REGISTRO_LONGITUD_NRO_POLIZA_NO_VALIDA);
		}
	}

	private void validarPreguntaSeguridad(String preguntaSeguridad, Errors errors)
	{
		validarRequerido(errors, CAMPO_PREGUNTA_SEGURIDAD);
		if (!errors.hasFieldErrors(CAMPO_PREGUNTA_SEGURIDAD)
				&& !RegularExpressionUtil.validar(RegularExpressionUtil.EXREG_ALFANUMERICO_ESPACIOS, preguntaSeguridad))
		{
			rechazarValor(errors, CAMPO_PREGUNTA_SEGURIDAD, MessageCodeConstant.MSJ_ERROR_NOT_VALID,
					"Pregunta de Seguridad");
		}
	}

	private void validarRequerido(Errors errors, String field)
	{
		validarRequerido(errors, field, MessageCodeConstant.MSJ_ERROR_REQUIRED1, "Campo");
	}

	private void validarRespuestaSeguridad(String respuestaSeguridad, Errors errors)
	{
		validarRequerido(errors, CAMPO_RESPUESTA_SEGURIDAD);
		if (!errors.hasFieldErrors(CAMPO_RESPUESTA_SEGURIDAD)
				&& !RegularExpressionUtil
						.validar(RegularExpressionUtil.EXREG_ALFANUMERICO_ESPACIOS, respuestaSeguridad))
		{
			rechazarValor(errors, CAMPO_RESPUESTA_SEGURIDAD, MessageCodeConstant.MSJ_ERROR_NOT_VALID, "Respuesta ");
		}
	}

	private void validarTelefonoContacto(String telefonoContacto, Errors errors)
	{
		if (!errors.hasFieldErrors(CAMPO_TELEFONO_CONTACTO)
				&& !RegularExpressionUtil.validar(RegularExpressionUtil.EXREG_TLF_FIJO, telefonoContacto))
		{
			rechazarValor(errors, CAMPO_TELEFONO_CONTACTO, MessageCodeConstant.MSJ_ERROR_REGISTRO_FORMAT_TLF_CONTACTO);
		}
	}

	private void validarTelefonosContacto(String telefonoContacto, String anexoContacto, Errors errors)
	{
		if (StringUtils.isBlank(telefonoContacto) && StringUtils.isBlank(anexoContacto))
		{
			rechazarValor(errors, CAMPO_TELEFONO_CONTACTO,
					MessageCodeConstant.MSJ_ERROR_REGISTRO_PORLOMENOS_UN_TLF_CONTACTO, null);
		}
		else
		{
			if (StringUtils.isNotBlank(telefonoContacto))
			{
				validarTelefonoContacto(telefonoContacto, errors);
			}
			else if (StringUtils.isNotBlank(anexoContacto))
			{
				validarAnexoContacto(anexoContacto, errors);
			}
		}
	}

	private void validarTerminosYCondiciones(boolean aceptaTerminos, Errors errors)
	{
		if (!aceptaTerminos)
		{
			rechazarValor(errors, CAMPO_ACEPTA_TERMINOS, MessageCodeConstant.MSJ_ERROR_REGISTRO_TERMINOS_CONDICIONES);
		}
	}
}